#!/usr/bin/env python -tt
# -*- coding: utf-8 -*-
# Autor: Pedro Moreira, 10015
# Data: 08/12/2011

import sqlite3
from   BeautifulSoup import BeautifulSoup
import urllib2
import SimpleHTTPServer
import SocketServer
import threading
from   sets import Set
import webbrowser as wb
import subprocess
import csv
import wx
from   pylab import *
import locale

class Teachers:
    '''
    Class para tratar dados estatísticos relativos a
    professores do Ensino Superior de Portugal
    '''

    def __init__(self):
        '''
        inicializa a classe e cria os dicionarios e sets a partir da bd
        '''
        locale.setlocale(locale.LC_NUMERIC, 'C') # resolver problema de unidades do gráfico
        print "fetching data"
        allRows = self.__getFromDB__('''SELECT id,
                                        nome,
                                        grau,
                                        curso,
                                        categoria,
                                        regime,
                                        ano,
                                        tipo_estabelecimento,
                                        nome_estabelecimento
                                        from teachers''')
        print "building data structures"
        # iniciar os dicionarios
        self.__graus, self.__cursos, self.__categorias = {},{},{}
        self.__regimes, self.__anos, self.__tiposEst = {},{},{}
        self.__estabelecimentos, self.__teachers = {},{}
        self.__ids, self.__nomes = {},{}

        # criar uma lista com todos os dicionarios
        self.__dicts = [ self.__ids, self.__nomes, self.__graus,
                         self.__cursos, self.__categorias,
                         self.__regimes, self.__anos,
                         self.__tiposEst, self.__estabelecimentos ]
        
        j = 0
        for row in allRows: # percorrer todos os registos
            if j in self.__teachers:
                # criar um dicionario com todos os dados de cada row
                for k in range(0,9):
                    self.__teachers[j].append(row[k])
                    pass
            else:
                self.__teachers[j] = []
                for k in range(0,9):
                    self.__teachers[j].append(row[k])
                    pass
                    
            for i in range(0,9): 
                if row[i] in self.__dicts[i]: # se o valor estiver já nas keys 
                    self.__dicts[i][row[i]].add(j) # adiciona o id do
                                                   # professor ao Set
                else:
                    self.__dicts[i][row[i]] = Set() # cria o key
                    self.__dicts[i][row[i]].add(j)  # adiciona o id do
                                                    # prodessor ao Set
                    pass #endif
                pass #end for in range(0,9)
            j = j + 1
        pass #end for in allRows
        # END __init__

    def getTeacher(self, tID):
        '''
        retorna as informações do professor no respectivo id do dicionário
        '''
        return self.__teachers[tID]
        # END getTeacher

    def getField(self, field):
        '''
        número do campo a pesquisar, 0 a 8
        id, nome, grau, curso, categoria, regime, ano,
        tipo de estabelecimento e nome de estabelecimento
        '''
        return sorted(self.__dicts[field])
        # END getFielddef autoInsertion(). 

        
    def genHTML(self, estabelecimento, categoria, grau):
        '''
        criar um ficheiro html com o filtro dos dados escolhidos
        iniciar o servidor http e tentar abrir o browser
        '''
        ###################################
        ## CRIAR FICHEIRO HTML
        ficheiro = file("index.html", "w")
        toFile = "<html> <head>"
        toFile += "<meta http-equiv=\"Content-Type\" "
        toFile += "content=\"text/html; charset=utf-8\" />"
        toFile += "<title>Rebides Statistics</title></head><body>"
        toFile += "<h0>Rebides Statistics</h0>"
        for ano in self.__anos:
            toFile += "<h1>Ano: {0}</h1><br>".format(ano)
            # A partir dos dados obtidos seleccionar os respectivos Set()
            # e fazer a sua intercepção até obter os ids em comum
            titulo = ""
            if estabelecimento > 0:
                estID = self.getField(8)[estabelecimento - 1]
                campo1 = self.__estabelecimentos[estID]
                titulo += estID + "<br>"
            else:
                campo1 = self.__anos[ano]
            if categoria > 0:
                catID = self.getField(4)[categoria - 1]
                campo2 = self.__categorias[catID]
                titulo += catID + "<br>"
            else:
                campo2 = self.__anos[ano]
            if grau > 0:
                grauID = self.getField(2)[grau - 1]
                campo3 = self.__graus[grauID]
                titulo += grauID + "<br>"
            else:
                campo3 = self.__anos[ano]
            lista = campo1 & campo2 & campo3 & self.__anos[ano]
            
            
            
            
            toFile += "<h3>{0} </h3><br>".format(titulo.encode("utf-8"))

            toFile += "<h4>Quantidade por estabelecimento</h4><ul>"
            for est in self.__estabelecimentos:
                current = len(lista & self.__estabelecimentos[est])
                if current > 0:
                    toFile += "<li>{0} - {1}</li>".format(est.encode("utf-8"), current)
            toFile += "</ul><h4>Quantidade por Categoria</h4><ul>"
            for cat in self.__categorias:
                current = len(lista & self.__categorias[cat])
                if current > 0:
                    toFile += "<li>{0} - {1}</li>".format(cat.encode("utf-8"), current)
            toFile += "</ul><h4>Quantidade por Grau</h4><ul>"
            for gr in self.__graus:
                current = len(lista & self.__graus[gr])
                if current > 0:
                    toFile += "<li>{0} - {1}</li>".format(gr.encode("utf-8"), current) 
            toFile += "</ul><br><h5>Lista</h5><ul>"
            for teacher in lista:
                toFile += "<li>"
                t = self.getTeacher(teacher)
                for i in t:
                    tchr = i
                    try:
                        tchr = tchr.encode("utf-8")
                        
                    except:
                        pass
                    toFile += "[{0}] ".format(tchr)
                toFile += "</li>"
                pass
            toFile += "</ul>"
            pass
        # END FOR POR ANOS
            
        toFile +="</body></html>"
        ficheiro.write(toFile)
        ficheiro.close()
        ###################################
        ## INCIAR O SERVIDOR HTTP
        try:
            self.thr = HttpServer()
            self.thr.start()
        except:
            pass
        ###################################
        ## ABRIR O BROWSER
        wb.open('http://localhost:8080')
        pass
        ###################################
        # END genHTML

       
    def genCSV(self,  estabelecimento, categoria, grau):
        '''
        criar um ficheiro CSV com o filtro dos dados escolhidos
        iniciar o servidor http e tentar abrir o browser
        '''
        # A partir dos dados obtidos seleccionar os respectivos Set()
        # e fazer a sua intercepção até obter os ids em comum
        estID = self.getField(8)[estabelecimento - 1]
        campo1 = self.__estabelecimentos[estID]
        titulo = estID
        if categoria > 0:
            catID = self.getField(4)[categoria - 1]
            campo2 = self.__categorias[catID]
        elif grau > 0:
            grauID = self.getField(2)[grau - 1]
            campo2 = self.__graus[grauID]
        else:
            campo2 = campo1
        lista = campo1 & campo2

        ###################################
        ## CRIAR FICHEIRO CSV
        filename = "output.csv"
        spamWriter = csv.writer(open(filename, 'wb'), delimiter=',',
                         quotechar='\x22', quoting=csv.QUOTE_MINIMAL)
        for t in lista:
            tchrs = self.getTeacher(t)
            spamWriter.writerow([str(tchrs[0])]
                                + [tchrs[1].encode('utf-8')]
                                + [tchrs[2].encode('utf-8')]
                                + [tchrs[3].encode('utf-8')]
                                + [tchrs[4].encode('utf-8')]
                                + [tchrs[5].encode('utf-8')]
                                + [tchrs[6].encode('utf-8')]
                                + [tchrs[7].encode('utf-8')]
                                + [tchrs[8].encode('utf-8')]
                                )
        ###################################
        ## TENTAR ABRIR O FICHEIRO WINDOWS / UNIX
        try:
            os.startfile(filename)
        except:
            try:
                subprocess.Popen(['xdg-open', filename])
            except:
                print "file saved!"
                pass
            pass
        pass
        ###################################
        # END genCSV
        

    def genGraph(self,  estabelecimento, categoria, grau):
        '''
        desenhar um gráfico dados os valores ys nos anos disponíveis na bd
        '''
        t = self.__anos.keys() # obter todos os anos da db

        ###################################
        ## CRIAR LISTA COM OS TOTAIS
        s = []
        for i in t:
            s.append(self.getTotal(i, estabelecimento, categoria, grau))

        ###################################
        ## CRIAR FUNÇÃO PARA GERAR UMA LISTA
        ## DE 1 ATÉ AO TAMANHO DOS DADOS
        ## E DESENHAR O GRÁFICO
        a = lambda:range(1, len(t) + 1)
         
        plot(a(), s)
        locs, labels = xticks(a(), self.__anos.keys())
        setp(labels, 'rotation', 'vertical')
        suptitle("REBIDES", fontsize=20)
        show()
        pass
        # END genGraph

        
    def countTags(self, urlText): # wxGlade: tStats.<event_handler>
        '''
        Contar os tags no url fornecido
        '''
        sopa = Soup() #!?
        sopas = sopa.findTags(urlText)
        output = ""
        for x in sopas:
            output += "<" + x + ">:" + str(sopas[x]) + " "
        print output
        # END countTags
        

    def getTotal(self, ano, estabelecimento, categoria, grau):
        '''
        Obter o total de docentes de acordo com os dados escolhidos
        '''
        # A partir dos dados obtidos seleccionar os respectivos Set()
        # e fazer a sua intercepção até obter os ids em comum
        estID = self.getField(8)[estabelecimento - 1]
        campo1 = self.__estabelecimentos[estID]
        titulo = estID
        if categoria > 0:
            catID = self.getField(4)[categoria - 1]
            campo2 = self.__categorias[catID]
        elif grau > 0:
            grauID = self.getField(2)[grau - 1]
            campo2 = self.__graus[grauID]
        else:
            campo2 = campo1
        lista = campo1 & campo2
        lista = lista & self.__anos[ano]
        return len(lista)
        # END getTotal
        

    def __getFromDB__(self, query):
        '''
        obter dados da DB
        '''
        try:
            self.__connection = sqlite3.connect("teachers.db")
        except:
            return "ERROR READING DATABASE"
        self.__c = self.__connection.cursor()
        self.__c.execute(query)
        self.__connection.commit()
        a = self.__c.fetchall()
        self.__connection.close()
        return a
        # END OF __getFromDB__()
    
    pass
    # END OF CLASS Teachers


class Soup:
    '''
    Obter a quantidade de tags html num sítio web
    tags: h1, h2, h3, div, p, ul, ol
    inspiração: aula(!!!)
    '''
    def findTags(self, url):
        '''
        obter as quantidades de tags utilizados
        '''
        page = urllib2.urlopen(url)
        soup = BeautifulSoup(page)
        lista = ["h1", "h2", "h3", "div", "p", "ul", "ol"]
        tags = {}
        for tag in lista:
            tags[tag] = len(soup.findAll(tag))
            pass
        return tags
        # END OF findTags()
    #END OF CLASS Soup


class HttpServer(threading.Thread):
    '''
    servidor http na porta 8080
    '''
    # utilizar através de um thread para não bloquear a aplicação
    def __init__(self):
        super(HttpServer, self).__init__()
        self._stop = threading.Event()

        self.__PORT = 8080
        handler = SimpleHTTPServer.SimpleHTTPRequestHandler
        self.__httpd = SocketServer.TCPServer(("", self.__PORT), handler)

    def run(self):
        '''
        iniciar o servidor
        '''
        self.__httpd.serve_forever()

    def stop(self):
        self._stop.set()
        self.__httpd.shutdown()
        self.__httpd.close_request()

    def stopped(self):
        return self._stop.isSet()

        pass
    #ENDOF CLASS HttpServer
